import { effect, track, trigger, ITERATE_KEY } from "./index.js";

// 5.4 合理的触发响应

let user = {
  foo: NaN,
};
// const ITERATE_KEY = Symbol();
let userProxy = new Proxy(user, {
  get(target, key, receiver) {
    track(target, key);
    return Reflect.get(target, key, receiver);
  },
  set(target, key, val, receiver) {
    const oldVal = target[key];
    // 如果属性不存在，则说明是在添加新属性，否则是设置已有属性
    const type = Object.prototype.hasOwnProperty.call(target, key)
      ? "SET"
      : "ADD";
    const res = Reflect.set(target, key, val, receiver);
    // if (oldVal !== val) {
    //   trigger(target, key, type);
    // }

    // 如果 p.foo 的初始值是 NaN，并且后续又为其设置了NaN 作为新值，那么仅仅进行全等比较的缺陷就暴露了
    // 解决NaN === NaN为false的问题（NaN !== NaN为true）
    if (oldVal !== val && (oldVal === oldVal || val === val)) {
      trigger(target, key, type);
    }
    return res;
  },
  has(target, key) {
    return Reflect.has(target, key);
  },
  ownKeys(target, key) {
    track(target, ITERATE_KEY);
    return Reflect.ownKeys(target);
  },
});

effect(() => {
  console.log("effect==", userProxy.foo);
});
// setTimeout(() => {
//   userProxy.foo = 1;
// }, 1500);

// 封装一个reactive函数
function reactive(target) {
  return new Proxy(target, {
    get(target, key, receiver) {
      if (key === "raw") {
        console.log(999999, key);
        return target;
      }
      // console.log("get===", target, key);
      track(target, key);
      return Reflect.get(target, key, receiver);
    },
    set(target, key, val, receiver) {
      const oldVal = target[key];
      // 如果属性不存在，则说明是在添加新属性，否则是设置已有属性
      const type = Object.prototype.hasOwnProperty.call(target, key)
        ? "SET"
        : "ADD";
      const res = Reflect.set(target, key, val, receiver);
      // if (oldVal !== val) {
      //   trigger(target, key, type);
      // }

      if (target === receiver.raw) {
        console.log(" receiver 就是 target 的代理对象");
        // 如果 p.foo 的初始值是 NaN，并且后续又为其设置了NaN 作为新值，那么仅仅进行全等比较的缺陷就暴露了
        // 解决NaN === NaN为false的问题（NaN !== NaN为true）
        if (oldVal !== val && (oldVal === oldVal || val === val)) {
          trigger(target, key, type);
        }
      }

      return res;
    },
    has(target, key) {
      return Reflect.has(target, key);
    },
    ownKeys(target, key) {
      track(target, ITERATE_KEY);
      return Reflect.ownKeys(target);
    },
  });
}

// 由原型引起的变更，从而产生不必要的更新操作
// reactive函数只是对proxy进行了一层封装，例子
const obj = {};
const proto = { bar: 1 };
const child = reactive(obj);
const parent = reactive(proto);
// 使用parent作为child的原型
Object.setPrototypeOf(child, parent);
effect(() => {
  console.log(child.bar);
});
child.bar = 2;
